// $Id: sp_convertible.hpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

//  Copyright 2008 Peter Dimov
//
//  Distributed under the Boost Software License, Version 1.0.
//  See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt

//
// Copyright notice reproduced from <boost/detail/sp_convertible.hpp>, from
// which this code was originally taken.
//
// Modified by Joseph Wu to fits the library.
//

#ifndef XPCOM_DETAIL_SP_CONVERTIBLE_HPP
#define XPCOM_DETAIL_SP_CONVERTIBLE_HPP

#include <xpcom/config.hpp>

#if !defined(XPCOM_NO_SP_CONVERTIBLE) && defined(BOOST_NO_SFINAE)
#  define XPCOM_NO_SP_CONVERTIBLE
#endif

#if !defined(XPCOM_NO_SP_CONVERTIBLE) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 303)
#  define XPCOM_NO_SP_CONVERTIBLE
#endif

#if !defined(XPCOM_NO_SP_CONVERTIBLE) && defined(__BORLANDC__) && (__BORLANDC__ <= 0x610)
#  define XPCOM_NO_SP_CONVERTIBLE
#endif

#ifndef XPCOM_NO_SP_CONVERTIBLE

namespace xpcom {
namespace detail {

template <typename U, typename T>
struct sp_convertible
{
    typedef char (&yes) [1];
    typedef char (&no)  [2];

    static yes f( T* );
    static no  f( ... );

    enum _vt { value = sizeof( f( static_cast<U*>(0) ) ) == sizeof(yes) };
};

struct sp_empty
{
};

template <bool>
struct sp_enable_if_convertible_impl;

template <>
struct sp_enable_if_convertible_impl<true>
{
    typedef sp_empty type;
};

template <>
struct sp_enable_if_convertible_impl<false>
{
};

template <typename U, typename T>
struct sp_enable_if_convertible :
    public sp_enable_if_convertible_impl<sp_convertible<U, T>::value>
{
};

} // namespace xpcom::detail
} // namespace xpcom

#endif // XPCOM_NO_SP_CONVERTIBLE

#endif // XPCOM_DETAIL_SP_CONVERTIBLE_HPP
